﻿#pragma once
#include <Windows.h>
#include <vector>
#include <string>
namespace SignatureUtils {
	/**
	 * @brief 在指定模块的特定区段中搜索特征码（字节序列）
	 * @param moduleName 目标模块名称（如"module.dll"），必须已加载到进程
	 * @param signature 特征码字节序列（如{0x56, 0x48, ...}），支持完整匹配
	 * @param sectionName 目标区段名称（如".text"），默认为".text"（代码区段）
	 * @param searchDirection 搜索方向，true=正向（从头到尾），false=反向（从尾到头）
	 * @param matchIndex 获取第几个匹配项（从0开始，默认0=第一个匹配），用于多次出现的特征码
	 * @return 匹配到的地址指针（void*），未找到返回nullptr
	 *
	 * 示例：
	 * // 示例1：基本用法
	 * std::vector<BYTE> sig = {0x48, 0x89, 0x5C, 0x24, 0x08};
	 * void* addr = FindSignatureInSection("module.dll", sig);
	 *
	 * // 示例2：反向搜索.text段中的第二个匹配项
	 * void* addr2 = FindSignatureInSection("module.dll", sig, ".text", false, 1);
	 */

	void* FindSignatureInSection(
		const char* moduleName,
		const std::vector<BYTE>& signature,
		const char* sectionName = ".text",
		bool searchDirection = true,
		size_t matchIndex = 0
	);

	/**
	 * @brief 在指定模块的特定区段中搜索带掩码的特征码（支持通配符）
	 * @param moduleName 目标模块名称（如"module.dll"），必须已加载到进程
	 * @param signature 特征码字节序列（如{0x48, 0x8B, 0x00, 0xC3}）
	 * @param mask 掩码字节序列（如{0xFF, 0xFF, 0x00, 0xFF}），0xFF=精确匹配，0x00=通配
	 * @param sectionName 目标区段名称（如".text"），默认为".text"
	 * @param searchDirection 搜索方向，true=正向（从头到尾），false=反向（从尾到头）
	 * @param matchIndex 获取第几个匹配项（从0开始，默认0=第一个匹配）
	 * @return 匹配到的地址指针（void*），未找到返回nullptr
	 *
	 * 示例：
	 * // 示例1：基本用法
	 * std::vector<BYTE> sig = {0x48, 0x8B, 0x00, 0xC3};
	 * std::vector<BYTE> mask = {0xFF, 0xFF, 0x00, 0xFF};
	 * void* addr = FindSignatureWithMaskInSection("module.dll", sig, mask);
	 *
	 * // 示例2：搜索.rdata段中的特征码
	 * void* addr2 = FindSignatureWithMaskInSection("module.dll", sig, mask, ".rdata");
	 */

	void* FindSignatureWithMaskInSection(
		const char* moduleName,
		const std::vector<BYTE>& signature,
		const std::vector<BYTE>& mask,
		const char* sectionName = ".text",
		bool searchDirection = true,
		size_t matchIndex = 0
	);

	/**
	 * @brief 直接用字符串格式（如"48 8B ?? C3"）描述特征码，支持??通配符
	 * @param moduleName 目标模块名称（如"module.dll"），必须已加载到进程
	 * @param signatureStr 特征码字符串（std::string），字节间用空格分隔，??表示通配符
	 * @param sectionName 目标区段名称（如".text"），默认为".text"
	 * @param searchDirection 搜索方向，true=正向（从头到尾），false=反向（从尾到头）
	 * @param matchIndex 获取第几个匹配项（从0开始，默认0=第一个匹配）
	 * @return 匹配到的地址指针（void*），未找到返回nullptr
	 *
	 * @example
	 * // 示例1：基本用法
	 * void* addr1 = FindSignatureStringInSection("module.dll", "48 8B ?? C3");
	 *
	 * // 示例2：从string对象读取特征码
	 * std::string signatureStr = "48 8B ?? C3";
	 * void* addr2 = FindSignatureStringInSection("module.dll", signatureStr, ".data");
	 */

	void* FindSignatureStringInSection(
		const char* moduleName,
		const std::string& signatureStr,
		const char* sectionName = ".text",
		bool searchDirection = true,
		size_t matchIndex = 0
	);

	/**
	 * @brief 开发专用接口：扫描整个模块并打印特征码信息（全模块扫描）
	 * @param moduleName 目标模块名称（如"module.dll"）
	 * @param signatureStr 特征码字符串（如"48 8B 05 ?? ?? ?? ?? 48 85 C0 74 0A"）
	 * @return 第一个匹配的地址指针（可选），未找到返回nullptr
	 *
	 * 此函数会扫描整个模块（所有区段），自动识别特征码所在的区段，并打印每个匹配项的详细信息（包括所在区段、绝对地址和相对偏移）。
	 * 同时会输出用于发布版本的硬编码调用示例。
	 *
	 * 注意：此函数主要用于开发阶段，用于获取特征码的偏移量。在发布版本中应使用GetHardcodedAddress。
	 *
	 * @example
	 * // 示例1：扫描module.dll中的特征码
	 * void* addr = DevFindSignature("module.dll", "48 8B 05 ?? ?? ?? ?? 48 85 C0 74 0A");
	 *
	 * // 示例2：从string对象读取特征码
	 * std::string signatureStr = "48 8B ?? C3";
	 * void* addr2 = DevFindSignature("module.dll", signatureStr);
	 * 
	 * // 输出示例（日志）：
	 * // ==================================================
	 * // [开发模式] 特征码搜索: 48 8B 05 ?? ?? ?? ?? 48 85 C0 74 0A
	 * // 模块: module.dll (基址: 0x00007FFA45000000, 大小: 0x156000)
	 * // 扫描模式: 全模块扫描
	 * // ==================================================
	 * // 匹配项 #1:
	 * //   所在区段: .text
	 * //   绝对地址: 0x00007FFA45123A80
	 * //   相对偏移: 0x123A80
	 * //   发布接口调用: GetHardcodedAddress("module.dll", 0x123A80, 0x156000)
	 * // ==================================================
	 * // 总计匹配: 1 个特征码
	 * // 第一个匹配地址: 0x00007FFA45123A80 (可选返回)
	 */
	void* DevFindSignature(
		const char* moduleName,
		const std::string& signatureStr
	);

	/**
	 * @brief 发布时接口：使用硬编码值快速定位地址（用于发布阶段）
	 * @param moduleName 目标模块名称
	 * @param hardcodedOffset 硬编码的偏移量
	 * @param expectedModuleSize 预期的模块大小（用于校验）
	 * @return 找到的地址指针，校验失败返回nullptr
	 *
	 * @example
	 * // 示例：使用开发阶段获取的硬编码值
	 * void* addr = GetHardcodedAddress("module.dll", 0x123A80, 0x156000);
	 */
	void* GetHardcodedAddress(
		const char* moduleName,
		uintptr_t hardcodedOffset,
		size_t expectedModuleSize
	);
};